home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d1
/
clipasc.arc
/
CLIPASC.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-03-17
|
24KB
|
1,070 lines
;----------------------------------------------------------------
; CLIPASC - ASCII file access from Clipper. W85 or later
; required.
; Description:
; CLIPASC is a set of functions which allow Clipper to
; open and manipulate flat ASCII files rather than needing
; to convert them to dBASE format first.
; Language:
; CLIPASC was written using Microsoft(C) Macro Assembler
; version 4.0
; Version:
; Version 1.1 - 2/26/87
; Author:
; Ben Cohen
; 12 Britton St.
; Jersey City, NJ 07306
; Change History:
; v1.1 - Fix _retxx calls so that they restore ES and BP
; before call.
; - Change combine class of code seg to 'PROG' to
; hide it in Clipper's code.
;----------------------------------------------------------------
include ascscan.mac
dgroup group dataseg
dataseg segment public 'DATA'
db 'CLIPASC ' ; eye-grabber
clip_save_es dw ? ; save area for ES
last_ret_cd dw ? ; return codes - retrieved by ASCRETCD
null_str db 00h,00h
;------ Data for OPENASC
open_parms dw 2,character,character
openasc_flags db ? ; flag byte
open_mode db 4 dup (?) ; mode to use for opening
openasc_tname db 128 dup (?) ; temp space for name
;------ Data for CLOSEASC
close_parms dw 1,numeric
;------ Data for LINEIN
linein_parms dw 1,numeric
linein_handle dw ?
linein_high dw ?
linein_low dw ?
linein_buf db 512 dup (?)
db 00h
;------ Data for LINEOUT
lineout_parms dw 2,numeric,character
lineout_handle dw ?
lineout_buf db 512 dup (?)
db 0d,0ah ; just in case it's that long
;------ Data for CHARIN
charin_parms dw 2,numeric,numeric+optional
charin_handle dw ?
;------ Data for CHAROUT
charout_parms dw 2,numeric,character+optional
charout_handle dw ?
;------ Data for ASCLSEEK
asclseek_parms dw 3,numeric,character+optional,numeric+optional
asclseek_handle dw ?
asclseek_method db ?
asclseek_high dw ?
asclseek_low dw ?
dataseg ends
clipasc segment public 'PROG'
public openasc
public closeasc
public ascretcd
public linein
public charin
public lineout
public charout
public asclseek
assume cs:clipasc,ds:dgroup
err_dos_base equ 4096 ; base errcode for a DOS errcode '0'
err_inv_parms equ 8192 ; errcode for invalid # of parms
err_parms_base equ 8200 ; base errcode for invalid parm # 0
;----------------------------------------------------------------
; OPENASC
; Description:
; Using passed info, open ASCII file in read,
; write, or read/write mode and then, possibly
; position the pointer to end of file for
; appending.
; Input:
; _par(0) = 2
; _parc(1) = fully qualified file name and ext.
; _parc(2) = 'r' - read mode, beginning
; 'w' - write mode, create file, beginning
; 'rw' - read/write mode, beginning, create if non-existant
; 'w+' - write mode, append to file, end of file
; 'rw+' - read/write mode, appending, end of file
; Returns:
; _retni() = file handle if ok
; -1 if error, error code available with ASCRETCD
;----------------------------------------------------------------
err_inv_mode equ 8301 ; Invalid access mode
open_jump_end equ 0001h ; jump to end of file
open_chk_file equ 0002h ; see if file exists - if not, create
db 'CLIPASC ' ; eye-grabber
openasc proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
cld ; forward, please
;------ Check that parms are ok
parm_chk dgroup:open_parms,openasc_ret_bad
;------ Now lets get the info
mov clip_save_es,es ; save ES for future
get_char 2
mov es,ax ; get segment
mov si,bx ; get offset
mov di,offset dgroup:open_mode ; where to put it
openasc_copy_mode:
mov al,es:[si] ; get next character
or al,al ; is it zero yet?
jz openasc_mode_done
mov ds:[di],al ; save the character
inc si ; next character position
inc di
jmp openasc_copy_mode ; next character
openasc_mode_done:
mov ds:[di],al ; store the final 00h
mov al,00h
mov openasc_flags,al
mov si,offset dgroup:open_mode
lodsb ; get first character of mode
cmp al,'r' ; read (partial or only)?
je openasc_reads
cmp al,'w' ; better be write, then.
je openasc_writes
mov ax,err_inv_mode ; nope, time to go
jmp openasc_ret_bad
;------ Write modes, check for '+' and make sure nothing else
openasc_writes:
lodsb ; check next byte
cmp al,00h ; write only?
je openasc_create ; yup, create the file
cmp al,'+' ; append?
je openasc_wrt_apd ; yup
mov ax,err_inv_mode ; bad mode
jmp openasc_ret_bad
;------ Read or read/write modes, still have to check
openasc_reads:
lodsb
cmp al,00h ; read only?
je openasc_read ; yup
cmp al,'w' ; better be read/write
je openasc_rw ; yup, check for appending
mov ax,err_inv_mode
jmp openasc_ret_bad
;------ Read/write mode. Have to check for appending
openasc_rw:
lodsb ; next character
cmp al,00h ; read/write at beginning?
je openasc_rd_wrt ; yup
cmp al,'+' ; appending also?
je openasc_rw_apd ; yup
mov ax,err_inv_mode ; bad mode
jmp openasc_ret_bad
;------ Have to create the file
openasc_create:
mov ah,03ch ; create function (DOS)
mov cx,0000h ; no attributes
jmp openasc_common
;------ Appending to existing file
openasc_wrt_apd:
lodsb ; that better have been it
cmp al,00h ; check to make sure
je open_wrt_apd_1 ; yeah, it's ok
mov ax,err_inv_mode ; bad mode
jmp openasc_ret_bad
open_wrt_apd_1:
or openasc_flags,open_chk_file+open_jump_end
; needs to be there and we want to be
; at the end
mov ah,03dh ; open file (DOS)
mov al,00010001b ; access mode flags (exclusive)
jmp openasc_common
;------ Read only file
openasc_read:
mov ah,03dh ; open file (DOS)
mov al,01000000b ; access mode flags
jmp openasc_common
;------ Read/write access at beginning
openasc_rd_wrt:
mov ah,03dh ; open file (DOS)
mov al,00010010b ; access mode flags (exclusive)
jmp openasc_common
;------ Read/write with appending
openasc_rw_apd:
lodsb ; make sure string ends
cmp al,00h ; check to make sure
je open_rw_apd_1 ; yup, ok
mov ax,err_inv_mode ; bad mode
jmp openasc_ret_bad
open_rw_apd_1:
or openasc_flags,open_chk_file+open_jump_end
; needs to be there and we want to be
; at the end
mov ah,03dh ; open file (DOS)
mov al,00010010b ; access mode flags (exclusive)
jmp openasc_common
;------ Common code for all opening types
openasc_common:
mov es,clip_save_es
push ax ; save important regs
push cx
get_char 1 ; get pointer to name.ext
mov cx,ds ; set ES = DS
mov es,cx
mov di,offset dgroup:openasc_tname
mov dx,di ; save it for later
mov ds,ax
mov si,bx
mov cx,128 ; max ASCIIZ string len
rep movsb ; don't care if we get extra
mov ax,es ; restore DS
mov ds,ax
mov es,clip_save_es ; restore ES
;------ Let's make a first crack at it
pop cx ; restore important regs
pop ax
int 21h ; go do it
jnc openasc_openok
test openasc_flags,open_chk_file ; make it if it's not there?
jnz openasc_chk_ocd
add ax,err_dos_base ; give them the code
jmp openasc_ret_bad
;------ Check opening code and see if we got 'file not found' when we should
openasc_chk_ocd:
cmp ax,2 ; file not found?
je openasc_crtit ; yeah, create it
add ax,err_dos_base ; give them the code
jmp openasc_ret_bad
openasc_crtit:
mov ah,03ch ; create file (DOS)
mov cx,0000h ; no attributes
mov dx,offset dgroup:openasc_tname ; get name
int 21h ; create it now
jnc openasc_openok ; good create
add ax,err_dos_base
jmp openasc_ret_bad
;------ Got good opening. Check for jump to end
openasc_openok:
test openasc_flags,open_jump_end
jz openasc_ret_gd
push ax ; save handle
mov bx,ax ; get handle in right reg
mov ah,042h ; LSEEK (DOS)
xor cx,cx ; don't want to move it
xor dx,dx
mov al,2 ; except to the end
int 21h ; go do it
jc openasc_fail_seek
pop ax ; get handle
jmp openasc_ret_gd
openasc_fail_seek:
add ax,err_dos_base
jmp openasc_ret_bad
openasc_ret_gd:
push ax
xor ax,ax ; want 0 return code
mov last_ret_cd,ax
pop ax
jmp short openasc_ret
;------ Have retcode in AX, set return number to -1 and save retcode
openasc_ret_bad:
mov last_ret_cd,ax
xor ax,ax
dec ax
jmp short openasc_ret
openasc_ret:
mov es,clip_save_es
mov sp,bp
pop es
pop bp
ret_int ax
ret
openasc endp
;----------------------------------------------------------------
; ASCRETCD
; Description:
; This procedure will return the real return code from the
; previously called function. This is to permit returning
; of an error code for those functions that can only take
; a character string as a return value.
; Input:
; None
; Output:
; _retni() = last return code for ASCII functions.
;----------------------------------------------------------------
ascretcd proc far
mov ax,last_ret_cd
ret_int ax
ret
ascretcd endp
;----------------------------------------------------------------
; CLOSEASC
; Description
; This procedure will close an ASCII file based on the file
; handle that is passed to it.
; Input:
; _par(0) = 1
; _parni(1) = file handle to close
; Output:
; _retni() = 0 if close ok
; -1 if error, error code accessible by ASCRETCD
;----------------------------------------------------------------
closeasc proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
cld ; forward, please
parm_chk dgroup:close_parms,closeasc_ret_bad
get_int 1 ; get the file handle
mov bx,ax ; into correct reg
mov ah,03eh ; close file (DOS)
int 21h ; go do it
jnc closeasc_ret_gd
add ax,err_dos_base
jmp closeasc_ret_bad
closeasc_ret_gd:
xor ax,ax
mov last_ret_cd,ax
jmp short closeasc_ret
closeasc_ret_bad:
mov last_ret_cd,ax
xor ax,ax
dec ax
jmp short closeasc_ret
closeasc_ret:
mov sp,bp
pop es
pop bp
ret_int ax
ret
closeasc endp
;----------------------------------------------------------------
; LINEIN
; Description:
; This procedure will read in a line of text from a flat
; ASCII file, truncate CRLF and return the line to the
; parent routine.
; Input:
; _par(0) = 1
; _parni(1) = file handle to read from
; Output:
; _retc() = line returned. If len(line) = 0, return code
; from ASCRETCD should be checked for error
; condition. Return code = -1 if EOF reached.
;----------------------------------------------------------------
err_too_long equ 8400 ; line > 512 bytes
linein proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
mov clip_save_es,es
cld ; forward, please
;------ Check our parameters
parm_chk dgroup:linein_parms,linein_ret_bad
;------ Ok, now let's find out what's going on...
get_int 1 ; get file handle
mov bx,ax ; put in right reg
mov linein_handle,bx
mov ah,042h ; LSEEK (DOS)
xor cx,cx ; no movement
xor dx,dx
mov al,1 ; move from current
int 21h
jnc linein_savcnt
add ax,err_dos_base ; error of some kind
jmp linein_ret_bad
;------ Save the pointer location. It's important
linein_savcnt:
mov linein_high,dx ; save old file pointers
mov linein_low,ax
mov ah,03fh ; read file (DOS)
mov bx,linein_handle ; get handle
mov dx,offset dgroup:linein_buf ; get loc of buf
mov cx,size linein_buf ; get length of buf
int 21h ; go do it
jnc linein_count
add ax,err_dos_base ; error code
jmp linein_ret_bad
;------ Did we hit EOF?
linein_count:
cmp ax,0000 ; are we at eof?
jne linein_scan
xor ax,ax
dec ax
jmp linein_ret_bad ; it's not an error, persay, but the
; results are the same
;------ Scan for EOF/CRLF combinations.
linein_scan:
mov si,offset dgroup:linein_buf ; get start of buffer
mov al,00
mov cx,size linein_buf
linein_scan_1:
mov ah,al ; save last character
lodsb
cmp ax,0d0ah ; check for CRLF
je linein_crlf
cmp al,01ah ; check for EOF
je linein_eof
loop linein_scan_1
mov ax,err_too_long
jmp linein_ret_gd
;------ Handle a CRLF sequence in file
linein_crlf:
push si ; save our current loc
sub si,2 ; don't count CRLF
mov byte ptr ds:[si],00h ; end of string
pop si ; get # of bytes read
sub si,offset dgroup:linein_buf
mov cx,linein_high ; restore pointers
mov dx,linein_low
add dx,si ; add number of bytes read
adc cx,0
mov ah,042h ; LSEEK (DOS)
mov al,0 ; from beginning of file
mov bx,linein_handle ; get file handle
int 21h
jnc linein_finish ; ok, now just clean up
add ax,err_dos_base
jmp linein_ret_bad
;------ Handle stumbling across EOF in file
linein_eof:
xor ax,ax
dec ax ; -1 for EOF
jmp linein_ret_bad ; bad type handling
;------ Clean up...
linein_finish:
xor ax,ax
jmp linein_ret_gd
linein_ret_gd:
mov last_ret_cd,ax
mov ax,dgroup
mov bx,offset dgroup:linein_buf
jmp short linein_ret
linein_ret_bad:
mov last_ret_cd,ax
mov ax,dgroup
mov bx,offset dgroup:null_str
jmp short linein_ret
linein_ret:
mov es,clip_save_es
mov sp,bp
pop es
pop bp
ret_char ax,bx
ret
linein endp
;----------------------------------------------------------------
; LINEOUT
; Description:
; This procedure will take the passed string and write it
; out to the specified flat ASCII file.
; Input:
; _par(0) = 2
; _parni(1) = file handle to write to
; _parc(2) = string to write. must be <= 512 bytes long.
; Output:
; _retni() = 0 if ok
; -1 if error. Error code accessable by ASCRETCD
;----------------------------------------------------------------
lineout proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
mov clip_save_es,es
cld ; forward, please
;------ Check our parameters
parm_chk dgroup:lineout_parms,lineout_ret_bad
;------ Get info
get_int 1 ; get the file handle
mov lineout_handle,ax ; save it for later use
get_char 2 ; get seg:off of string
push ds ; save seg regs for later
push es
mov es,ax ; get segment
mov di,bx ; get offset
push di ; save start of string
mov al,00h ; search for end of string
xor cx,cx ; count until found
dec cx
repne scasb ; look for it
not cx ; how many did we scan through
dec cx ; one too many - don't count 00h
pop si ; restore that to keep stack clean
cmp cx,size lineout_buf ; too big?
jle lineout_copy_line ; nope, keep goint
;------ String is greater than buffer size
pop es ; restore regs
pop ds
mov ax,err_too_long ; give 'em something to think about
jmp lineout_ret_bad
;------ Have to copy the string over
lineout_copy_line:
mov ax,es ; DS = ES - set source to target
mov ds,ax
mov di,offset dgroup:lineout_buf
mov dx,di ; save location for later
pop es ; restore ES for copy
rep movsb ; copy string over
mov al,0dh ; send out CR
stosb
mov al,0ah ; send out LF
stosb
sub di,offset dgroup:lineout_buf
mov cx,di ; get number of bytes to write
pop ds ; restore regs
mov ah,040h ; write to a file (DOS)
mov bx,lineout_handle
int 21h
jnc lineout_ret_gd
add ax,err_dos_base
jmp lineout_ret_bad
lineout_ret_gd:
xor ax,ax
mov last_ret_cd,ax
jmp short lineout_ret
lineout_ret_bad:
mov last_ret_cd,ax
xor ax,ax
dec ax
jmp short lineout_ret
lineout_ret:
mov es,clip_save_es
mov sp,bp
pop es
pop bp
ret_int ax
ret
lineout endp
;----------------------------------------------------------------
; CHARIN
; Description:
; This procedure will read a specified number of bytes from
; a passed file handle. There will be no translation of the
; information read, whatsoever.
; Input:
; _par(0) = 1|2
; _parni(1) = file handle to read from
; _parni(2) = number of characters to read. must be <= 512
; optional - defaults to 1 character
; Output:
; _retc() = characters read. If len(line) = 0, return
; code from ASCRETCD should be checked for error
; condition. Return code = -1 if EOF reached.
;----------------------------------------------------------------
charin proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
mov clip_save_es,es
;------ Check parameters
parm_chk dgroup:charin_parms,charin_ret_bad
;------ Get the file handle and other info
get_int 1
mov charin_handle,ax ; save the handle
get_ptype 2
cmp ax,undef ; did they tell us how many?
jne charin_how_many
mov ax,1 ; default to 1 byte
jmp charin_read ; and go do it
charin_how_many:
get_int 2
cmp ax,size linein_buf ; using buffer from linein
jle charin_read
mov ax,err_too_long
jmp charin_ret_bad
charin_read:
mov cx,ax ; get count to use
mov dx,offset dgroup:linein_buf
add ax,dx
push ax ; save addr of next char for later
mov ah,3fh ; read from file (DOS)
mov bx,charin_handle
int 21h
pop bx ; restore addr to clean up stack
jnc charin_check_eof
add ax,err_dos_base
jmp charin_ret_bad
charin_check_eof:
or ax,ax ; check how many bytes read
jnz charin_set_str ; no, everything's ok
xor ax,ax
dec ax ; set -1 ret code for EOF
jmp charin_ret_bad ; same processing
charin_set_str:
mov byte ptr ds:[bx],00h ; 00h terminator
xor ax,ax
jmp charin_ret_gd
charin_ret_gd:
mov last_ret_cd,ax
mov ax,dgroup
mov bx,offset dgroup:linein_buf
jmp short charin_ret
charin_ret_bad:
mov last_ret_cd,ax
mov ax,dgroup
mov bx,offset dgroup:null_str
jmp short charin_ret
charin_ret:
mov es,clip_save_es
mov sp,bp
pop es
pop bp
ret_char ax,bx
ret
charin endp
;----------------------------------------------------------------
; CHAROUT
; Description:
; This procedure will write out the character string which
; was passed to it, or, if no character string was passed,
; will truncate the specified file.
; Input:
; _par(0) = 1|2
; _parni(1) = handle of file to write to
; _parc(2) = string to be written out
; optional - if not given, truncates file
; at current write pointer
; Output:
; _retni() = 0 if ok
; -1 if error, retcode accessible with ASCRETCD
;----------------------------------------------------------------
charout proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
mov clip_save_es,es
;------ Get our parameters and check them
parm_chk dgroup:charout_parms,charout_ret_bad
;------ Let's do something with our parameters
get_int 1 ; get the file handle
mov charout_handle,ax ; and save it for later
get_char 2 ; get what we have to write
mov es,ax ; get segment
mov di,bx ; get offset
mov al,00h ; find end of string
xor cx,cx ; do it until we find it
dec cx
push di ; save start of string for later
repne scasb ; find it...
not cx ; turn it positive
dec cx ; and don't count the 00h
pop dx ; need offset in DX
mov bx,charout_handle ; restore handle
push ds
mov ax,es
mov ds,ax ; need segment in DS
mov ah,040h ; write file (DOS)
int 21h ; and go do it
pop ds ; restore dataseg before all else
jnc charout_ret_gd
add ax,err_dos_base
jmp charout_ret_bad
charout_ret_gd:
xor ax,ax
mov last_ret_cd,ax
jmp short charout_ret
charout_ret_bad:
mov last_ret_cd,ax
xor ax,ax
dec ax
jmp short charout_ret
charout_ret:
mov es,clip_save_es
mov sp,bp
pop es
pop bp
ret_int ax
ret
charout endp
;----------------------------------------------------------------
; ASCLSEEK
; Description:
; This procedure implements the DOS LSEEK function which
; allows positioning within a file.
; Input:
; _par(0) = 1|2|3
; _parni(1) = file handle to work with
; _parc(2) = 'b'|'B' - offset from beginning of file
; 'c'|'C' - offset from current position in file
; 'e'|'E' - offset from end of file
; if not given, defaults to 'c'
; _parni(3) = length to move from location given in _parc(2)
; if not given, defaults to 0
; Output:
; _retnl() = current pointer within file, or -1 if error
; if error, retcode available from ASCRETCD
;----------------------------------------------------------------
err_bad_method equ 8401
err_bad_offset equ 8402
;------ Equates for pointer movement methods
offset_bof equ 00h
offset_cur equ 01h
offset_eof equ 02h
asclseek proc far
ifdef debug
int 3
endif
push bp
push es
mov bp,sp
mov clip_save_es,es
;------ Check our parameters
parm_chk dgroup:asclseek_parms,asclseek_ret_bad
;------ Start playing with them...
get_int 1 ; get the file handle
mov asclseek_handle,ax ; and save it for later
mov al,offset_cur ; default method
mov asclseek_method,al ; save it
get_ptype 2 ; did they give us a method
cmp ax,undef
jne asclseek_parse_meth ; go scan the method
jmp asclseek_get_offset
;------ We've got a method. Find out what it is.
asclseek_parse_meth:
get_char 2 ; get the string
mov es,ax ; get segment
mov di,bx ; get offset
mov ax,es:[di] ; get the string
mov es,clip_save_es ; restore ES immediately
cmp ah,00h ; only one character?
je asclseek_chk_meth
mov ax,err_bad_method ; set error code
jmp asclseek_ret_bad
;------ Got it. Now check against accepted ones.
asclseek_chk_meth:
or al,'a'-'A' ; to lower case
cmp al,'c' ; Current pos?
jne asclseek_chk_1
mov al,offset_cur
jmp asclseek_save_meth
asclseek_chk_1:
cmp al,'b' ; Beginning of file
jne asclseek_chk_2
mov al,offset_bof
jmp asclseek_save_meth
asclseek_chk_2:
cmp al,'e' ; End of file
jne asclseek_bad_meth
mov al,offset_eof
jmp asclseek_save_meth
asclseek_bad_meth:
mov ax,err_bad_method ; set error code
jmp asclseek_ret_bad
asclseek_save_meth:
mov asclseek_method,al
;------ Did they give us an offset to move?
asclseek_get_offset:
xor ax,ax
mov asclseek_high,ax ; set defaults
mov asclseek_low,ax
get_ptype 3 ; did they give us an offset?
cmp ax,undef
jne asclseek_chk_offset
jmp asclseek_move
;------ Get what the offset is and do minimal checking
asclseek_chk_offset:
get_long 3
mov asclseek_high,ax ; save it
mov asclseek_low,bx ; both bytes of it
cmp asclseek_method,offset_eof ; starting from EOF?
jne asclseek_move ; nope, keep going
or ax,ax ; yes. Did they give us an offset?
jnz asclseek_bad_off
or bx,bx ; how about low byte?
jz asclseek_move
asclseek_bad_off:
mov ax,err_bad_offset ; set error code
jmp asclseek_ret_bad
asclseek_move:
mov bx,asclseek_handle ; get handle
mov cx,asclseek_high ; get high byte of offset
mov dx,asclseek_low ; get low byte of offset
mov al,asclseek_method ; get movement method
mov ah,042h ; LSEEK
int 21h
jnc asclseek_ret_gd
add ax,err_dos_base ; set DOS error code
jmp asclseek_ret_bad
asclseek_ret_gd:
xor bx,bx
mov last_ret_cd,ax
jmp short asclseek_ret
asclseek_ret_bad:
mov last_ret_cd,ax
xor ax,ax
dec ax
mov dx,ax
jmp short asclseek_ret
asclseek_ret:
mov sp,bp
pop es
pop bp
ret_long dx,ax
ret
asclseek endp
clipasc ends
end